﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.Environment.Extensions;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Rework.CommerceHistory.Models;
using Orchard.Data;
using Orchard.Roles.Models;
using Orchard;
using Orchard.UI.Notify;
using Orchard.Localization;

namespace Rework.CommerceHistory.Handlers {
    [OrchardFeature("Rework.CommerceRoleAssignment")]
    public class CommerceRoleAssignmentHandler : ContentHandler {
        private readonly IRepository<UserRolesPartRecord> _userRolesRepository;
        private readonly IRepository<CommerceProductRolesRecord> _productRolesRepository;
        private readonly INotifier _notifier;

        public CommerceRoleAssignmentHandler(
            IRepository<CommerceRoleAssignmentPartRecord> repository
            , IRepository<UserRolesPartRecord> userRolesRepository
            , IRepository<CommerceProductRolesRecord> productRolesRepository
            , INotifier notifier) {
            T = NullLocalizer.Instance;
            Filters.Add(StorageFilter.For(repository));

            // Load up the Product Roles list for display purposes
            _productRolesRepository = productRolesRepository;
            Filters.Add(new ActivatingFilter<CommerceRoleAssignmentPart>("CommerceRoleAssignment"));
            OnLoaded<CommerceRoleAssignmentPart>((context, productRoles) => {
                productRoles.Roles = _productRolesRepository
                    .Fetch(x => x.ProductId == context.ContentItem.Id)
                    .Select(x => x.Role.Name).ToList();
            });

            // Every time a product makes it to the history, we need to try and implement roles
            _userRolesRepository = userRolesRepository;
            _notifier = notifier;
            
            OnCreated<CommerceHistoryPart>((context, part) => ImplementProductRoleAssignment(part));
            OnPublished<CommerceHistoryPart>((context, part) => ImplementProductRoleAssignment(part));
            OnUpdated<CommerceHistoryPart>((context, part) => ImplementProductRoleAssignment(part));
        }

        public Localizer T { get; set; }
        
        private void ImplementProductRoleAssignment(CommerceHistoryPart part) {
            if (part.IsPaymentConfirmed) {
                // Grab the part.Product and see if it has an CommerceRoleAssignmentPart
                if (part.Product.Has<CommerceRoleAssignmentPart>()) {
                    // If it does, we need to try and add roles - we don't remove roles using this process
                    var currentUserRoleRecords = _userRolesRepository.Fetch(x => x.UserId == part.UserId);
                    var currentRoleRecords = currentUserRoleRecords.Select(x => x.Role);
                    var targetRoleRecords = _productRolesRepository.Fetch(x => x.ProductId == part.ProductId).Select(x => x.Role);
                    foreach (var addingRole in targetRoleRecords.Where(x => !currentRoleRecords.Contains(x))) {
                        _notifier.Warning(T("Adding role {0} to user {1}", addingRole.Name, part.User.UserName));
                        _userRolesRepository.Create(new UserRolesPartRecord { UserId = part.UserId, Role = addingRole });
                    }
                    //foreach (var removingRole in currentUserRoleRecords.Where(x => !targetRoleRecords.Contains(x.Role))) {
                    //    _notifier.Warning(T("Removing role {0} from user {1}", removingRole.Role.Name, part.User.UserName));
                    //    _userRolesRepository.Delete(removingRole);
                    //}
                }
            }
        }
    }

}